import math, os, sys, poser, random, string

os.chdir( os.path.dirname(poser.AppLocation()) )
sys.path.append(os.path.join("Runtime","Python","Poseworks","Particles3","data"))

from prt3Constants import *

import prt3Node

class PwPoserObject(object):
    def __init__(self, obj):
        self.source = obj
    def write(self):
        pass
    def Name(self):
        return self.source.Name()

class PwPoserParameter(PwPoserObject):
    def write(self):
        return "\n\t\tvalueParm %s" % self.source.InternalName() +\
               "\n\t\t\t{" +\
               "\n\t\t\tkeys" +\
               "\n\t\t\t\t{" +\
               "\n\t\t\t\tk 0 %f" % self.source.Value() +\
               "\n\t\t\t\t}" +\
               "\n\t\t\t}"
    def writeNameValue(self):
        return "\n\t%s %i" % (self.source.InternalName(), int(self.source.Value()))

class PwPoserActor(PwPoserObject):
    def __init__(self, obj, autobuild=0):
        PwPoserObject.__init__(self, obj)
        self.channels = []
        if autobuild:
            for parm in obj.Parameters():
                self.addChannel(parm)
    def addParameter(self, name):
        parm = self.source.Parameter(name)
        if parm:
            self.addChannel(parm)
        else:
            print "Warning! Skipping parameter '%s'..." % name
    def addChannel(self, parm):
        self.channels.append( PwPoserParameter(parm) )
    def removeChannel(self, name):
        for i in range( len(self.channels) ):
            if self.channels[i].Name() == name:
                self.channels.remove(i)
                break
    def write(self):
        parms = ""
        for channel in self.channels:
            parms = parms + channel.write()
        return "\n\nactor %s" % self.source.InternalName() +\
               "\n\t{" +\
               "\n\tchannels" +\
               "\n\t\t{" +\
               parms +\
               "\n\t\t}" +\
               "\n\t}"

class PwSystemData(PwPoserActor):
    def __init__(self, obj):
        PwPoserActor.__init__(self, obj)
        self.properties = []
        name = self.source.ItsFigure().Name()
        self.addStringProperty("name", name)
        parm = self.source.Parameter(PARM_COUNT)
        if parm:
            self.addIntProperty("count", parm.Value())
        shapeGeom = ""
        shape = int(obj.Parameter(PARM_SHAPE).Value())
        if shape != SHAPE_CUSTOM:
            shapeGeom = {  SHAPE_BALL : GEOM_BALL,
                           SHAPE_TORUS: GEOM_TORUS,
                           SHAPE_PILL : GEOM_PILL,
                           SHAPE_SPRITE: GEOM_SPRITE,
                           SHAPE_CONE : GEOM_CONE }[shape]
        else:
            shapeGeom = askShapeLocation()
        self.addStringProperty("shape", shapeGeom)
    def addIntProperty(self, name, value):
        self.properties.append( (name, int(value)) )
    def addStringProperty(self, name, value):
        self.properties.append( (name, "\"" + value + "\"") )
    def write(self):
        parms = ""
        for channel in self.channels:
            parms = parms + channel.writeNameValue()
        props = ""
        for prop, val in self.properties:
            props = props + "\n\t%s %s" % (prop, val)
        return "\n\nPRT3_Group" +\
               "\n\t{" +\
               parms +\
               props +\
               "\n\t}"

class PwPose(object):
    def __init__(self):
        self.actors = []
        self.figure = []
    def addActor(self, actor):
        self.actors.append(actor)
    def addToFigure(self, element):
        self.figure.append(element)
    def write(self):
        actors = ""
        for actor in self.actors:
            actors = actors + actor.write()
        figure = ""
        for element in self.figure:
            figure = figure + element.write()
        return "{" +\
               "\nversion" +\
               "\n\t{" +\
               "\n\tnumber 3.0" +\
               "\n\t}" +\
               actors +\
               "\n\nfigure" +\
               "\n\t{" +\
               figure +\
               "\n\t}" +\
               "\n}"

def savePreset(figure, outpath):
    body = figure.ParentActor()
    matData = prt3Node.PwPoserMaterial(figure.Materials()[0])
    sysData = PwSystemData(body)
    bodyData = PwPoserActor(body)
    bodyParms = (PARM_EMISSION,
                 PARM_RECYCLE,
                 PARM_LIFESPAN,
                 PARM_START,
                 PARM_END,
                 PARM_GRAVITY,
                 PARM_VELOCITYX, PARM_VELOCITYY, PARM_VELOCITYZ,
                 PARM_ACCELERATIONX, PARM_ACCELERATIONY, PARM_ACCELERATIONZ,
                 PARM_VELOCITYVAR,
                 PARM_ORBITX, PARM_ORBITY, PARM_ORBITZ,
                 PARM_ORBITAX, PARM_ORBITAY, PARM_ORBITAZ,
                 PARM_ORBITVAR,
                 PARM_SPINX, PARM_SPINY, PARM_SPINZ,
                 PARM_SPINAX, PARM_SPINAY, PARM_SPINAZ,
                 PARM_SPINVAR,
                 PARM_GROWX, PARM_GROWY, PARM_GROWZ,
                 PARM_GROWAX, PARM_GROWAY, PARM_GROWAZ,
                 PARM_GROWVAR,
                 PARM_PSCALE,
                 PARM_PXROTATE, PARM_PYROTATE, PARM_PZROTATE,
                 PARM_PXTRAN, PARM_PYTRAN, PARM_PZTRAN )
    for parm in bodyParms:
        bodyData.addParameter(parm)
    pose = PwPose()
    pose.addActor(sysData)
    pose.addActor(bodyData)
    pose.addToFigure(matData)
    output = pose.write()
    fi = open(outpath, 'w')
    fi.write(output)
    fi.close()

class PwSystemCollector(object):
    def __init__(self):
        self.options = {}
    def collect(self, line):
        cleaned = self.clean(line)
        if cleaned == "}":
            return 0
        elif cleaned == "{":
            return 1
        elif not cleaned:
            return 1
        else:
            name, value = self.format(line)
            self.options[name] = value
            return 1
    def format(self, line):
        divided = line.split()
        name = divided[0]
        value = string.join(divided[1:], " ")
        if value[0] == "\"":
            value = value[1:-1]
        else:
            value = float(value)
        return name, value
    def clean(self, line):
        return line.strip()
    def get(self):
        return self.options

def readPreset(inpath):
    import string
    fi = open(inpath)
    fir = fi.readlines()
    fi.close()
    sysCollector = PwSystemCollector()
    i = 0
    sysStart = -1
    for line in fir:
        cleaned = line.strip()
        if cleaned == "PRT3_Group":
            sysStart = i + 2
            break
        i = i + 1
    if sysStart > -1:
        i = sysStart
        line = fir[i]
        while sysCollector.collect(line):
            i = i + 1
            line = fir[i]
    return sysCollector.get()

def applyPreset(inpath):
    poser.Scene().LoadLibraryPose(inpath)
    figure = poser.Scene().CurrentFigure()
    prt3Node.copyMaterials(figure.ParentActor(), figure)

def loadPreset(inpath):
    import prt3Core
    sysData = readPreset(inpath)
    prt3Core.createSystem(sysData["name"], [(sysData["name"], sysData["count"], sysData["shape"])])
    applyPreset(inpath)

if __name__ == '__main__':
    #savePreset(poser.Scene().CurrentFigure(), os.path.join(DIR_HOME, "Runtime", "libraries", "pose", "Prt3 Preset.pz2"))
    #readPreset(os.path.join(DIR_HOME, "Runtime", "libraries", "pose", "Prt3 Preset.pz2"))
    loadPreset(os.path.join(DIR_HOME, "Runtime", "libraries", "pose", "Prt3 Preset.pz2"))
